#pragma once

#include "People.h"

#include <cassert>

#define PEOPLE_COMPARISON_FUNCTION(name, method) \
	inline bool PeopleComparison##name(const People* const i_a, const People* const i_b) \
	{ return i_a->method > i_b->method; } 

PEOPLE_COMPARISON_FUNCTION(Match, GetHistory().GetMatch());
PEOPLE_COMPARISON_FUNCTION(Resistance, GetSkills().m_physicsSkills[Resistance]);
PEOPLE_COMPARISON_FUNCTION(Stamina, GetSkills().m_physicsSkills[Stamina]);
PEOPLE_COMPARISON_FUNCTION(Fatigue, GetSkills().m_physicsSkills[Fatigue]);
PEOPLE_COMPARISON_FUNCTION(Intelligence, GetSkills().m_mentalSkills[Intelligence]);
PEOPLE_COMPARISON_FUNCTION(Charisma, GetSkills().m_mentalSkills[Charisma]);
PEOPLE_COMPARISON_FUNCTION(Agressivity, GetSkills().m_mentalSkills[Aggressivity]);
PEOPLE_COMPARISON_FUNCTION(Salary, GetSalary());
PEOPLE_COMPARISON_FUNCTION(Goal, GetHistory().GetScoredGoal());
PEOPLE_COMPARISON_FUNCTION(TotalGoal, GetHistory().GetTotalScoredGoal());
PEOPLE_COMPARISON_FUNCTION(NumInjury, GetHistory().GetNumOfInjury());
PEOPLE_COMPARISON_FUNCTION(TotalNumInjury, GetHistory().GetTotalNumOfInjury());
PEOPLE_COMPARISON_FUNCTION(TotalDayInjury, GetHistory().GetTotalNumOfInjuryDays());
PEOPLE_COMPARISON_FUNCTION(TotalDisciplinePoints, GetHistory().GetTotalDisciplinePoints());
PEOPLE_COMPARISON_FUNCTION(Expulsion, GetHistory().GetTotalRedCard());
PEOPLE_COMPARISON_FUNCTION(Admonition, GetHistory().GetTotalYellowCard());
PEOPLE_COMPARISON_FUNCTION(AveragePlayerSkills, GetSkills().m_playerSkills.GetAverageSkills());
PEOPLE_COMPARISON_FUNCTION(AverageTrainerSkills, GetSkills().m_trainerSkills.GetAverageSkills());
PEOPLE_COMPARISON_FUNCTION(SellValue, SellValue());
PEOPLE_COMPARISON_FUNCTION(Evaluation, GetHistory().GetEval());
PEOPLE_COMPARISON_FUNCTION(MoM, GetHistory().GetMoM());
PEOPLE_COMPARISON_FUNCTION(TotalMoM, GetHistory().GetTotalMoM());

inline bool PeopleComparisonAgeUp(const People* const i_a, const People* const i_b)
{
	return i_a->GetHistory().GetAge() > i_b->GetHistory().GetAge();
}

inline bool PeopleComparisonAgeDown(const People* const i_a, const People* const i_b)
{
	return i_a->GetHistory().GetAge() < i_b->GetHistory().GetAge();
}

inline bool PeopleComparisonPlayerAgeUp(const People* const i_a, const People* const i_b)
{
	return i_a->GetHistory().GetPlayerAge() > i_b->GetHistory().GetPlayerAge();
}

inline bool PeopleComparisonPlayerAgeDown(const People* const i_a, const People* const i_b)
{
	const int ageA = i_a->GetHistory().GetPlayerAge();
	const int ageB = i_b->GetHistory().GetPlayerAge();
	return (ageA != 0 ? ageA : 10000000) < (ageB != 0 ? ageB : 10000000);
}

inline bool PeopleComparisonSameID(const People* const i_a, const People* const i_b)
{
	return i_a->GetId() == i_b->GetId();
}

struct PeopleComparisonTotalMatch
{
	explicit PeopleComparisonTotalMatch(const int i_status):m_status(i_status){}
	bool operator()(const People* const i_a, const People* const i_b) const
	{
		return i_a->GetHistory().GetTotalMatch(m_status) > i_b->GetHistory().GetTotalMatch(m_status);
	}
	int m_status;
};

struct PeopleComparisonNumSeason
{
	explicit PeopleComparisonNumSeason(const int i_status):m_status(i_status){}
	bool operator()(const People* const i_a, const People* const i_b) const
	{
		return i_a->GetHistory().GetNumSeason(m_status) > i_b->GetHistory().GetNumSeason(m_status);
	}
	int m_status;
};

inline bool PeopleComparisonTotalGoalRatio(const People* const i_a, const People* const i_b)
{
	if(((i_a->GetHistory().GetTotalMatch(StatusPlayer) < 100) && (i_b->GetHistory().GetTotalMatch(StatusPlayer) < 100)) ||
		((i_a->GetHistory().GetTotalMatch(StatusPlayer) >= 100) && (i_b->GetHistory().GetTotalMatch(StatusPlayer) >= 100)))
	{
		return i_a->GetHistory().GetTotalScoredGoalRatio() > i_b->GetHistory().GetTotalScoredGoalRatio();
	}

	return i_a->GetHistory().GetTotalMatch(StatusPlayer) > i_b->GetHistory().GetTotalMatch(StatusPlayer);
}

inline bool PeopleComparisonTotalEvaluation(const People* const i_a, const People* const i_b)
{
	if(((i_a->GetHistory().GetTotalMatch(StatusPlayer) < 100) && (i_b->GetHistory().GetTotalMatch(StatusPlayer) < 100)) ||
		((i_a->GetHistory().GetTotalMatch(StatusPlayer) >= 100) && (i_b->GetHistory().GetTotalMatch(StatusPlayer) >= 100)))
	{
		return i_a->GetHistory().GetTotalEval() > i_b->GetHistory().GetTotalEval();
	}

	return i_a->GetHistory().GetTotalMatch(StatusPlayer) > i_b->GetHistory().GetTotalMatch(StatusPlayer);
}

inline bool PeopleBuyChoose(const People* const i_a, const People* const i_b)
{
	assert(i_a->GetStatus() == StatusPlayer && i_b->GetStatus() == StatusPlayer);

	const int w1 = 10;
	const int w3 = -10;
	const int w4 = -500;

	const int weightA = w1 * i_a->GetSkills().m_playerSkills.GetAverageSkills() + w3 * i_a->GetHistory().GetAge() + w4 * i_a->GetAvailability().GetDaysBroken();
	const int weightB = w1 * i_b->GetSkills().m_playerSkills.GetAverageSkills() + w3 * i_b->GetHistory().GetAge() + w4 * i_b->GetAvailability().GetDaysBroken();

	return weightA > weightB;
}

struct PeopleComparisonSkill
{
	explicit PeopleComparisonSkill(const int i_skill):m_skill(i_skill){}
	bool operator()(const People* const i_a, const People* const i_b) const
	{
		return (i_a->GetSkills().m_playerSkills[m_skill] > i_b->GetSkills().m_playerSkills[m_skill]);
	}
	int m_skill;
};

struct PeopleComparisonMaxSkill
{
	explicit PeopleComparisonMaxSkill(const int i_skill):m_skill(i_skill){}
	bool operator()(const People* const i_a, const People* const i_b) const
	{
		return (i_a->GetSkills().m_maxPlayerSkills[m_skill] > i_b->GetSkills().m_maxPlayerSkills[m_skill]);
	}
	int m_skill;
};

struct PeopleComparisonID
{
	explicit PeopleComparisonID(int i_id):m_id(i_id){}
	bool operator()(const People* const i_a) const
	{
		return i_a->GetId() == m_id;
	}
	int m_id;
};

inline bool IsNotBroken(const People* const i_player)
{
	return !i_player->GetAvailability().IsBroken();
}

inline bool IsNotExpulse(const People* const i_player)
{
	return !i_player->GetAvailability().IsExpulse();
}
